package org.hujunfeng.http;

import java.io.*;
import java.io.FileInputStream;
import java.util.Date;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.text.SimpleDateFormat;

/**
 * @Author 胡俊丰
 * @Date 2024/7/23
 **/
public class Logger {

    /**
     * 文件字符打印器
     */
    private static FileWriter writer = null;

    /**
     * 日志文件的目录
     */
    private static String logDirectory = ".." + File.separator + "log/";

    /**
     * 本次使用的日志文件名
     */
    private static String logFileName = "";

    /**
     * 本次操作使用的日志文件
     */
    private static File logFile = null;

    /**
     * 日志的配置文件名字
     */
    private static String metaFileName =  "meta.txt";

    /**
     * 日志配置文件的路径
     */
    private static String metaFilePath = ".." + File.separator + "conf/";

    /**
     * 日志文件最大的字节数
     * 1MB
     */
    private static long logFileMaxSize = 10 * 1024 * 1024;

    static {
        openFile();
    }

    private Logger() {
    }

    /**
     * 打开文件
     */
    private static void openFile() {
        File logMetaFile = new File(metaFilePath, metaFileName);

        if (!logMetaFile.exists()) {
            try {
                throw new FileNotFoundException("meta.txt file is not found.");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } else {
            try {

                // 设置日志文件名
                logFileName = loadLogName(logMetaFile);

                // 如果为空，就生成一个            
                if (logFileName == null || logFileName.equals("")) {    
                    logFileName = getLogName();
                }

                // 获得日志文件对象
                logFile = new File(logDirectory, logFileName);

                // 如果不存在，就创建一个新文件
                if (!logFile.exists()) {
                    logFile.createNewFile();
                }

                // 初始化文件输出器，采用添加模式；
                writer = new FileWriter(logFile, true);
            } catch (IOException e) {
                e.printStackTrace();
            }

            // 保存一次配置
            store();
        }
    }

    /**
     * 获得日志文件名字的方法
     * @param record
     */ 
    private static String loadLogName(File file) throws IOException{
        String name = "";
        BuffReader reader = new BuffReader(new FileInputStream(file));
        String line = "";
        while(true){
            line = reader.readLine("\r\n", "UTF-8");
            if(line == null){
                break;
            }
            if(line.trim().startsWith("log_name=")){
                String temp = line.trim();
                if(temp.indexOf("=") != -1){
                    if((temp.indexOf("=") + 1) < (temp.length() - 1)){
                        name = temp.substring(temp.indexOf("=") + 1);
                        break;
                    }
                } 
            }
        }
        reader.close();
        return name; 
    }

    /**
     * 格式化日期
     * @param record
     */
    private static String getDateString(){
        // 定义当前的日期
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒SSS毫秒 E");
        return sdf.format(date);
    }

    /**
     * 打印日志的方法
     * @param record
     */
    public static synchronized void log(String record) {
        try {
            if (writer == null) {
                throw new NullPointerException("writer is not initialize.");
            }

            // 执行一次文件改变
            doChangeFile();

            // 输出一些字符串
            writer.write("[" + getDateString() + "]--" + record + "\r\n");

            // 刷新到文件里
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 改变文件，解决文件容量满了的情况
     */
    private static void doChangeFile() {
        if (hasHappen()) {
            try {
                // 关闭输出流
                writer.close();

                logFileName = getLogName();
                
                // 重新生成一个文件
                logFile = new File(logDirectory, logFileName);

                // 重新生成一个文件输出对象
                writer = new FileWriter(logFile, true);

                // 保存一次状态
                store();
            } catch (IOException var1) {
                var1.printStackTrace();
            }
        }

    }

    /**
     * 判断条件是否发生
     * @return
     */
    private static boolean hasHappen(){
        boolean condition = false;
        if (logFile != null){
            if (logFile.isFile() && logFile.exists() && (logFile.length() > logFileMaxSize)) {
                condition = true;
            }
        } else {
            condition = true;
        }

        return condition;
    }

    /**
     * 获得一个文件名
     * @return
     */
    public static String getLogName() {
        Date now = new Date();
        String tempLogName = "log-" + (1900 + now.getYear()) + "-" +
                ljust(String.valueOf(now.getMonth() + 1), 2) + "-" + ljust(String.valueOf(now.getDate()), 2) + "-[" + getRandomDigit(5) + "].txt";
        return tempLogName;
    }

    private static String getRandomDigit(int len) {
        Random random = new Random();
        int bound = Integer.parseInt("99999999999".substring(0, len));
        int tempInt = random.nextInt(bound);
        return String.valueOf(tempInt);
    }

    private static String ljust(String data, int len) {
        StringBuffer buffer = null;
        if (data.length() >= len) {
            return data;
        } else {
            buffer = new StringBuffer(data);
            int diff = len - buffer.length();

            for(int count = 1; count <= diff; ++count) {
                buffer.insert(0, "0");
            }

            return buffer.toString();
        }
    }

    /**
     * 保存一次当前的配置
     */
    private static void store(){
        try {
            String metaPath = metaFilePath + File.separator + metaFileName;
            FileOutputStream fous = new FileOutputStream(metaPath);
            fous.write(("log_name=" + logFileName + "\r\n").getBytes("UTF-8"));
            fous.flush();
            fous.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭日志
     */
    public static synchronized void close() {
        try {
            if (writer != null) {
                writer.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
